package org.jeecg.modules.externalEquity.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.jeecg.modules.externalEquity.entity.ExternalEquitySummary;
import org.jeecg.modules.externalEquity.entity.TbExternalEquity;
import org.jeecg.modules.externalEquity.mapper.TbExternalEquityMapper;
import org.jeecg.modules.externalEquity.service.ITbExternalEquityService;
import org.jeecg.modules.system.entity.SysDepart;
import org.jeecg.modules.system.enums.OrgLevelEnum;
import org.jeecg.modules.system.mapper.SysDepartMapper;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 4、对外股权投资
 * @Author: jeecg-boot
 * @Date: 2025-04-23
 * @Version: V1.0
 */
@Service
@Slf4j
public class TbExternalEquityServiceImpl extends ServiceImpl<TbExternalEquityMapper, TbExternalEquity> implements ITbExternalEquityService {

    @Resource
    private SysDepartMapper sysDepartMapper;

    @Resource
    private TbExternalEquityMapper tbExternalEquityMapper;


    @Override
    public List<TbExternalEquity> statistics(TbExternalEquity tbExternalEquity, Map<String, String[]> parameterMap) {
        List<TbExternalEquity> finalResult = new ArrayList<>();
        String[] depIds = parameterMap.get("companyId[]");
        if (depIds != null && depIds.length > 0 && !StringUtils.isEmpty(depIds[depIds.length - 1])) {
            String depId = depIds[depIds.length - 1];
            log.info("depId:{}", depId);
            SysDepart departById = sysDepartMapper.getDepartById(depId);
            String orgCode = departById.getOrgCode();
            tbExternalEquity.setOrgCode(orgCode);
        }
        List<TbExternalEquity> tbExternalEquities = tbExternalEquityMapper.selectSummerList(tbExternalEquity);

        Map<String, List<TbExternalEquity>> data = tbExternalEquities.stream()
                .collect(Collectors.groupingBy(
                        TbExternalEquity::getOrgCode,
                        LinkedHashMap::new, // 指定使用 LinkedHashMap
                        Collectors.toList()
                ));
        // 获取所有 key 的长度
        Set<Integer> uniqueLengths = new HashSet<>();
        for (String key : data.keySet()) {
            uniqueLengths.add(key.length());
        }

        // 将 Set 转换为数组
        int[] parentCodeLengths = uniqueLengths.stream().mapToInt(Integer::intValue).toArray();

        // 第一步 计算公司本部：对每个 key 的 List 中的收入进行汇总
        // 使用 Collectors.toMap 并指定使用 LinkedHashMap
        Map<String, ExternalEquitySummary> summaryMap = data.entrySet().stream()
                .collect(Collectors.toMap(
                        Map.Entry::getKey,
                        entry -> {
                            BigDecimal sumInitialInvestmentCost = entry.getValue().stream()
                                    .map(TbExternalEquity::getInitialInvestmentCost)
                                    .filter(Objects::nonNull)
                                    .reduce(BigDecimal.ZERO, BigDecimal::add);
                            BigDecimal sumCumulativeOriginalValue = entry.getValue().stream()
                                    .map(TbExternalEquity::getCumulativeOriginalValue)
                                    .filter(Objects::nonNull)
                                    .reduce(BigDecimal.ZERO, BigDecimal::add);
                            BigDecimal sumCumulativeNetValue = entry.getValue().stream()
                                    .map(TbExternalEquity::getCumulativeNetValue)
                                    .filter(Objects::nonNull)
                                    .reduce(BigDecimal.ZERO, BigDecimal::add);
                            BigDecimal sumCumulativeIncomeReceivable = entry.getValue().stream()
                                    .map(TbExternalEquity::getCumulativeIncomeReceivable)
                                    .filter(Objects::nonNull)
                                    .reduce(BigDecimal.ZERO, BigDecimal::add);
                            BigDecimal sumCumulativeIncomeReceived = entry.getValue().stream()
                                    .map(TbExternalEquity::getCumulativeIncomeReceived)
                                    .filter(Objects::nonNull)
                                    .reduce(BigDecimal.ZERO, BigDecimal::add);
                            BigDecimal sumCurrentYearIncomeReceived = entry.getValue().stream()
                                    .map(TbExternalEquity::getCurrentYearIncomeReceived)
                                    .filter(Objects::nonNull)
                                    .reduce(BigDecimal.ZERO, BigDecimal::add);

                            TbExternalEquity firstAssetManagement = entry.getValue().get(0);

                            BigDecimal sumValue = sumInitialInvestmentCost.add(sumCumulativeOriginalValue)
                                    .add(sumCumulativeNetValue).add(sumCumulativeIncomeReceivable)
                                    .add(sumCumulativeIncomeReceived).add(sumCurrentYearIncomeReceived);
                            boolean flag = sumValue.compareTo(BigDecimal.ZERO) == 0;

                            String companyLevel = firstAssetManagement.getCompanyLevel();
                            if (StringUtils.isEmpty(companyLevel)) {
                                companyLevel = OrgLevelEnum.getLevelByCodeLength(firstAssetManagement.getOrgCode().length());
                            }
                            return new ExternalEquitySummary(
                                    firstAssetManagement.getCompanyName() + "（本部）合计",
                                    firstAssetManagement.getOrgCode(),
                                    companyLevel,
                                    sumInitialInvestmentCost,
                                    sumCumulativeOriginalValue,
                                    sumCumulativeNetValue,
                                    sumCumulativeIncomeReceivable,
                                    sumCumulativeIncomeReceived,
                                    sumCurrentYearIncomeReceived,
                                    flag ? new LinkedList<>() : entry.getValue()
                            );
                        },
                        (oldValue, newValue) -> oldValue, // 合并函数，这里直接返回 oldValue
                        LinkedHashMap::new // 指定使用 LinkedHashMap
                ));

        // 创建 currentSummaryMap 的深拷贝
        Map<String, ExternalEquitySummary> currentSummaryMap = new LinkedHashMap<>();
        for (Map.Entry<String, ExternalEquitySummary> entry : summaryMap.entrySet()) {
            currentSummaryMap.put(entry.getKey(), entry.getValue().deepCopy());
        }
        log.info("打印公司本部汇总数据 currentSummaryMap :{}", JSONObject.toJSONString(currentSummaryMap));

        for (Map.Entry<String, ExternalEquitySummary> entry : summaryMap.entrySet()) {
            String code = entry.getKey();
            ExternalEquitySummary summary = entry.getValue();
            aggregateToParent(summaryMap, code, summary, parentCodeLengths);
        }

        Map<String, ExternalEquitySummary> containSummaryMap = new LinkedHashMap<>(summaryMap);
        for (Map.Entry<String, ExternalEquitySummary> entry : summaryMap.entrySet()) {
            containSummaryMap.put(entry.getKey(), entry.getValue().deepCopy());
        }
        log.info("打印公司总计汇总数据 包含本部 containSummaryMap :{}", JSONObject.toJSONString(containSummaryMap));


        // 创建一个新的 ExternalEquitySummary 对象用于汇总合计
        ExternalEquitySummary totalSummary = getTotalSummary(currentSummaryMap);
        TbExternalEquity totalAssetManagement = new TbExternalEquity();
        BeanUtils.copyProperties(totalSummary, totalAssetManagement);
        finalResult.add(totalAssetManagement);

        // 第三步：将汇总结果和原始数据合并到一个 List 中
        for (ExternalEquitySummary amount : containSummaryMap.values()) {

            TbExternalEquity amountAssetManagement = new TbExternalEquity();
            BeanUtils.copyProperties(amount, amountAssetManagement);
            finalResult.add(amountAssetManagement); //添加总计

            TbExternalEquity currentAssetManagement = new TbExternalEquity();
            ExternalEquitySummary current = currentSummaryMap.get(amount.getOrgCode());
            if (!amountAssetManagement.getCompanyName().equals(current.getCompanyName())) {
                BeanUtils.copyProperties(current, currentAssetManagement);
                finalResult.add(currentAssetManagement);//添加本部
            }

            finalResult.addAll(current.getExternalEquityList()); //添加本部计算的原始数据
        }
        // 打印结果
        log.info("Final Result:{}", JSONObject.toJSONString(finalResult));

        return finalResult;
    }

    @NotNull
    private static ExternalEquitySummary getTotalSummary(Map<String, ExternalEquitySummary> currentSummaryMap) {
        ExternalEquitySummary totalSummary = new ExternalEquitySummary(
                "汇总合计", // 公司名称
                "", // 公司代码
                "", // 公司级次
                BigDecimal.ZERO,
                BigDecimal.ZERO,
                BigDecimal.ZERO,
                BigDecimal.ZERO,
                BigDecimal.ZERO,
                BigDecimal.ZERO,
                new ArrayList<>()
        );
        // 遍历 currentSummaryMap，将所有值汇总到 totalSummary
        for (ExternalEquitySummary summary : currentSummaryMap.values()) {
            totalSummary.addCurrentYearIncomeReceived(summary.getCurrentYearIncomeReceived());
            totalSummary.addInitialInvestmentCost(summary.getInitialInvestmentCost());
            totalSummary.addCumulativeOriginalValue(summary.getCumulativeOriginalValue());
            totalSummary.addCumulativeNetValue(summary.getCumulativeNetValue());
            totalSummary.addCumulativeIncomeReceivable(summary.getCumulativeIncomeReceivable());
            totalSummary.addCumulativeIncomeReceived(summary.getCumulativeIncomeReceived());
        }
        return totalSummary;
    }

    // 定义一个方法，用于将子公司的数据加和到父公司
    private static void aggregateToParent(Map<String, ExternalEquitySummary> summaryMap, String code, ExternalEquitySummary summary, int[] parentCodeLengths) {
        for (int length : parentCodeLengths) {
            if (code.length() > length) {
                String parentCode = code.substring(0, length); // 获取父公司的代码
                if (summaryMap.containsKey(parentCode)) {
                    // 将子公司的数据加和到父公司
                    ExternalEquitySummary parentSummary = summaryMap.get(parentCode);
                    parentSummary.addCumulativeIncomeReceivable(summary.getCumulativeIncomeReceivable());
                    parentSummary.addCumulativeIncomeReceived(summary.getCumulativeIncomeReceived());
                    parentSummary.addCumulativeNetValue(summary.getCumulativeNetValue());
                    parentSummary.addCumulativeOriginalValue(summary.getCumulativeOriginalValue());
                    parentSummary.addInitialInvestmentCost(summary.getInitialInvestmentCost());
                    parentSummary.addCurrentYearIncomeReceived(summary.getCurrentYearIncomeReceived());
                    // 更新公司名称
                    String originalName = parentSummary.getCompanyName();
                    parentSummary.setCompanyName(originalName.replace("（本部）合计", "（公司）总计"));
                }
            }
        }
    }
}
